<?php

/*
 * Copyright 2008 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#namespace tehframework;

class ClassLoader
{
	const STORAGE_KEY = '0CBF9BF827DC1BA00A6E1DA021814221';
	
	/**
	 * @var array<string,string>
	 */
	private $classMap;
	
	/**
	 * @var Storage?
	 */
	private $storage;
	
	/**
	 * @var bool
	 */
	private $restored;
	
	/**
	 * @param  Storage? $storage
	 */
	public function __construct(Storage $storage = null)
	{
		if ($storage !== null)
		{
			$this->storage  = $storage;
			$this->classMap = (array)$this->storage->restore(self::STORAGE_KEY);
			$this->restored = !empty($this->classMap);
		}
		else
		{
			$this->classMap = array();
			$this->restored = false;
		}
	}
	
	public function __destruct()
	{
		if ($this->storage && !$this->restored)
		{
			$this->storage->store(self::STORAGE_KEY, $this->classMap);
		}
	}
	
	/**
	 * @param  array<string,string> $map
	 * @return ClassLoader
	 */
	public function addMap(array $map)
	{
		if (!$this->restored)
		{
			$this->classMap += $map;
		}
		
		return $this;
	}
	
	/**
	 * @param  RecursiveDirectoryIterator $directory
	 * @return ClassLoader
	 */
	public function addDirectory(RecursiveDirectoryIterator $directory)
	{
		if ($this->restored)
		{
			return $this;
		}
		
		/* @var $entry SplFileInfo */
		foreach ($directory as $entry)
		{
			if ($entry->isDir())
			{
				$this->addDirectory($directory->getChildren());
				
				continue;
			}
			
			$file = $entry->getFilename();
			
			if (ctype_upper($file[0]) && (substr($file, -4) === '.php'))
			{
				$this->classMap[substr($file, 0, -4)] = $entry->getPathname();
			}
		}
		
		return $this;
	}
	
	/**
	 * @param  string $className
	 * @return ClassLoader
	 */
	public function load($className)
	{
		if (isset($this->classMap[$className]))
		{
			include_once $this->classMap[$className];
		}
		
		return $this;
	}
}